/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2009, Around(J2)ME				                                 **
 **   All rights reserved.                                                   **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the New BSD License which accompanies this    			 **
 **   distribution.											                 **
 **   A copy is found in the textfile LICENSE.txt							 **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Main developers:                                                       **
 **     Juri Strumpflohner		http://blog.js-development.com	             **
 **		Matthias Braunhofer		http://matthias.jimdo.com                    **
 **                                                                          **
 **  **********************************************************************  */

package org.aroundme.persistency;

import java.util.List;

import org.aroundme.model.Place;
import org.aroundme.model.Search;
import org.aroundme.model.User;
import org.aroundme.utility.HibernateUtil;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

/**
 * Persistency class responsible for saving and retrieving Place-objects
 * from the DB
 * 
 */
public class PlaceManager {
	
	public PlaceManager(){
	}
	
	/**
	 * Saves a place to the DB. If it exists it will be modified, otherwise
	 * a new entry will be created
	 * @param p Place object to be saved
	 */
	public void savePlace(Place p){
		Session s = HibernateUtil.getSessionFactory().getCurrentSession();
		s.beginTransaction();
		try{
			s.saveOrUpdate(p);
			s.getTransaction().commit();
		}catch(HibernateException e){
			s.getTransaction().rollback();
			throw e;
		}
	}
	
	/**
	 * Deletes a Place object from the DB
	 * @param p Place object to be deleted
	 */
	public void deletePlace(Place p){
		Session s = HibernateUtil.getSessionFactory().getCurrentSession();
		s.beginTransaction();
		try{
			s.delete(p);
			s.getTransaction().commit();
		}catch(HibernateException e){
			s.getTransaction().rollback();
			throw e;
		}
	}
	
	/**
	 * Retrieves a Place object with the specified Id
	 * @param id ID of the place-object that should be retrieved
	 * @return Place object containing the place with the given id
	 */
	public Place retrievePlaceWithId(int id){
		Session s = HibernateUtil.getSessionFactory().getCurrentSession();
		Place result = null;
		s.beginTransaction();
		try{
			Criteria c = s.createCriteria(Place.class);
			c.add(Restrictions.eq("id", id));
			result = (Place) c.uniqueResult();
			s.getTransaction().commit();
		}catch(HibernateException e){
			s.getTransaction().rollback();
			throw e;
		}
		return result;
	}

	/**
	 * Returns all the places made by the user with id "userLoginName"
	 * @param userLoginName
	 * @param begin index point from which to start retrieving data
	 * @param amount amount of data to retrieve per call to the DB
	 * @return List<Place> containing the places of the given user
	 */
	public List<Place> retrieveUserPlaces(String userLoginName, int begin, int amount) {
		//TODO try to use criteria queries
		List<Place> result = null;
		Session s = HibernateUtil.getSessionFactory().getCurrentSession();
		s.beginTransaction();
		try{
			Criteria cUser = s.createCriteria(User.class);
			cUser.add(Restrictions.eq("loginName", userLoginName));
			User u = (User) cUser.uniqueResult();
			
			Criteria cPlace = s.createCriteria(Place.class);
			cPlace.add(Restrictions.eq("user", u));
			cPlace.addOrder(Order.desc("creationDate"));
			result = cPlace.setFirstResult(begin).setMaxResults(amount).list();
			s.getTransaction().commit();
		}catch(HibernateException e){
			s.getTransaction().rollback();
			e.printStackTrace();
			throw e;
		}
		return result;
	}
	
	/**
	 * Searches for a place in the DB
	 * @param search Search object containing search-information
	 * @param begin index point from which to start retrieving data
	 * @param dataAmount amount of data to retrieve per call to the DB
	 * @return List<Place> getting the place that match the current search
	 */
	public List<Place> searchPlaces(Search search, int begin, int dataAmount){
		List<Place> result = null;
		
		Session s = HibernateUtil.getSessionFactory().getCurrentSession();
		s.beginTransaction();
		try{
			Criteria c = s.createCriteria(Place.class);
			
			for (String tmp : search.getKeywordsAND()) {
				c.add(Restrictions.or(
						Restrictions.ilike("name", tmp, MatchMode.ANYWHERE),
						Restrictions.ilike("city", tmp, MatchMode.ANYWHERE)));
			}
			//prepare or expressions
			Disjunction disjunction = Restrictions.disjunction();
			for (String tmp : search.getKeywordsOR()) {
				disjunction.add(Restrictions.or(
						Restrictions.ilike("name", tmp, MatchMode.ANYWHERE),
						Restrictions.ilike("city", tmp, MatchMode.ANYWHERE)));
			}
			c.add(disjunction);
			
			result = c.setFirstResult(begin).setMaxResults(dataAmount).list();
			s.getTransaction().commit();
		}catch(HibernateException e){
			s.getTransaction().rollback();
			e.printStackTrace();
			throw e;
		}
		return result;
	}
	
	/**
	 * Retrieves all places
	 * @param begin index at which the retrieval should start
	 * @param maxAmount max-amount of data to be retrieved
	 * @return List containing the result-places
	 */
	public List<Place> retrieveAllPlaces(int begin, int maxAmount) {
		List<Place> result = null;
		Session s = HibernateUtil.getSessionFactory().getCurrentSession();
		s.beginTransaction();
		try{
			Criteria c = s.createCriteria(Place.class);
			c.addOrder(Order.desc("creationDate"));
			result = c.setFirstResult(begin).setMaxResults(maxAmount).list();
			s.getTransaction().commit();
		}catch(HibernateException e){
			s.getTransaction().rollback();
			throw e;
		}
		return result;
	}
	
}
